home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / graphics / display / mpega / src / audioport.a < prev    next >
Encoding:
Text File  |  1997-11-20  |  40.5 KB  |  1,418 lines

  1. ;------------------------------------------------------------------------------
  2. ;
  3. ;   File    :    AudioPort.a
  4. ;
  5. ;   Author  :    Stéphane TAVENARD
  6. ;
  7. ;   $VER:   AudioPort.a  1.3  (22/07/1995)
  8. ;
  9. ;   (C) Copyright 1995-1995 Stéphane TAVENARD
  10. ;    All Rights Reserved
  11. ;
  12. ;   #Rev|   Date   |              Comment
  13. ;   ----|----------|--------------------------------------------------------
  14. ;   0    |05/06/1995| Initial revision                      ST
  15. ;   1    |06/06/1995| First release (no more C code)                       ST
  16. ;   2    |19/06/1995| Added FreeSignal in DeletePort              ST
  17. ;   3    |23/06/1995| Aminet release                      ST
  18. ;   4    |09/07/1995| Use now ex_EClockFrequency for period calculation      ST
  19. ;   5    |22/07/1995| Added volume control for 16-bit samples          ST
  20. ;   5    |24/07/1995| Added Mixing frequency                  ST
  21. ;
  22. ;   ------------------------------------------------------------------------
  23. ;
  24. ;   An Audio Port 8 or 16 bits, mono or stereo
  25. ;
  26. ;------------------------------------------------------------------------------
  27.  
  28.  
  29.              IFND     INCLUDE_SOURCE
  30.              incdir   "include:"
  31.              include  "exec/funcdef.i"
  32.              include  "exec/exec.i"
  33.              include  "exec/exec_lib.i"
  34.              include  "devices/audio.i"
  35.              include  "hardware/custom.i"
  36.              ENDC
  37.  
  38.              include  "AudioPort.i"
  39.  
  40.              IFND     INCLUDE_SOURCE
  41.              XREF     _custom
  42.  
  43. CALLEXEC         MACRO
  44.              move.l  (_SysBase).w,a6
  45.              jsr     _LVO\1(a6)
  46.              ENDM
  47. _SysBase         EQU     4
  48.  
  49.              ENDC
  50.  
  51.  
  52.              XDEF     @AU_close
  53.              XDEF     @AU_open
  54.              XDEF     @AU_write
  55.  
  56. ; Audio registers
  57.  
  58. AU_PTR             equ   ac_ptr
  59. AU_LEN             equ   ac_len
  60. AU_PER             equ   ac_per
  61. AU_VOL             equ   ac_vol
  62. AU_DAT             equ   ac_dat
  63.  
  64. AUDIO_PRI         equ   ADALLOC_MAXPREC
  65.  
  66.              section  ASMDATA,data
  67.  
  68.              even
  69. AU_AllChannels         dc.b  15
  70.              even
  71. AU_LRChannels         dc.b  3, 5, 10, 12
  72.              even
  73. AU_DEVICE_NAME         AUDIONAME
  74.              even
  75. AU_PORT_NAME         dc.b  'AudioPort', 0
  76.  
  77.              section  ASMCODE,code
  78.  
  79. ;
  80. ;             Calculate audio period with help of frequency
  81. ;
  82. ;             d0.l = frequency
  83. ;             -> d0.l = period
  84. ;             a0, d1 is affected
  85. ;
  86. calculate_period
  87.              tst.l    d0
  88.              beq      calculate_period9
  89.              move.l   (_SysBase).w,a0
  90.              move.l   ex_EClockFrequency(a0),d1
  91.              mulu.l   #5,d1        ; d1 = Audio DMA base freq.
  92.              divu.l   d0,d1
  93. ;              move.l   #100000000,d1
  94. ;              mulu.w   #28,d0
  95. ;              divu.l   d0,d1
  96.              move.l   d1,d0
  97. calculate_period9    rts
  98.  
  99.  
  100. ;
  101. ;             Delete a port
  102. ;
  103. ;             a0:   MsgPort *
  104. ;
  105. DeletePort         movem.l  a2,-(sp)
  106.              move.l   a0,a2
  107.              tst.l    MP+LN_NAME(a2)
  108.              beq      DeletePort1
  109.              move.l   a2,a1
  110.              CALLEXEC RemPort
  111. DeletePort1         clr.l    d0
  112.              move.b   MP_SIGBIT(a2),d0
  113.              CALLEXEC FreeSignal
  114.              move.b   #-1,MP+LN_TYPE(a2)
  115.              move.l   #-1,MP_MSGLIST+LH_HEAD(a2)
  116.              move.l   a2,a1
  117.              move.l   #MP_SIZE,d0
  118.              CALLEXEC FreeMem
  119.              movem.l  (sp)+,a2
  120.              rts
  121. ;
  122. ;             Create a port
  123. ;
  124. ;             a0:   name
  125. ;             d0.b: pri
  126. ;             -> d0 = MsgPort * (=0 if fail)
  127. ;
  128. CreatePort         movem.l  a2-a3/d2-d3,-(sp)
  129.              move.l   d0,d2
  130.              move.l   a0,a2
  131.              moveq.b  #-1,d0
  132.              CALLEXEC AllocSignal
  133.              cmp.b    #-1,d0
  134.              beq      CreatePort8    ; Signal error
  135.              move.l   d0,d3
  136.              move.l   #MP_SIZE,d0
  137.              move.l   #MEMF_PUBLIC|MEMF_CLEAR,d1
  138.              CALLEXEC AllocMem
  139.              tst.l    d0
  140.              beq      CreatePort7    ; Memory error
  141.              move.l   d0,a3
  142.              move.l   a2,MP+LN_NAME(a3)
  143.              move.b   d2,MP+LN_PRI(a3)
  144.              move.b   #NT_MSGPORT,MP+LN_TYPE(a3)
  145.              move.b   #PA_SIGNAL,MP_FLAGS(a3)
  146.              move.b   d3,MP_SIGBIT(a3)
  147.              clr.l    d0
  148.              move.l   d0,a1
  149.              CALLEXEC FindTask
  150.              move.l   d0,MP_SIGTASK(a3)
  151.              tst.l    a2
  152.              beq      CreatePort1
  153.              move.l   a3,a1
  154.              CALLEXEC AddPort
  155.              move.l   a3,d0
  156.              bra      CreatePort9
  157. CreatePort1         lea      MP_MSGLIST(a3),a1
  158.              NEWLIST  a1
  159.              move.l   a3,d0
  160.              bra      CreatePort9
  161. CreatePort7         move.l   d3,d0
  162.              CALLEXEC FreeSignal
  163. CreatePort8         clr.l    d0
  164. CreatePort9         movem.l  (sp)+,a2-a3/d2-d3
  165.              rts
  166.  
  167. ;
  168. ;             Delete an Ext IORequest
  169. ;
  170. ;             a0:   IORequest *
  171. ;
  172. DeleteExtIO
  173.              tst.l    a0
  174.              beq      DeleteExtIO9
  175.              move.b   #-1,IO+MN+LN_TYPE(a0)
  176.              move.l   #-1,IO_DEVICE(a0)
  177.              move.l   #-1,IO_UNIT(a0)
  178.              move.l   a0,a1
  179.              clr.l    d0
  180.              move.w   IO+MN_LENGTH(a0),d0
  181.              CALLEXEC FreeMem
  182. DeleteExtIO9         rts
  183.  
  184. ;
  185. ;             Create an Ext IORequest
  186. ;
  187. ;             a0:   MsgPort *
  188. ;             d0.w: Size
  189. ;             -> d0 = IORequest * (=0 if fail)
  190. ;
  191. CreateExtIO         movem.l  a2/d2,-(sp)
  192.              tst.l    a0
  193.              beq      CreateExtIO9
  194.              and.l    #$0000FFFF,d0
  195.              move.l   d0,d2
  196.              move.l   a0,a2
  197.              move.l   #MEMF_PUBLIC|MEMF_CLEAR,d1
  198.              CALLEXEC AllocMem
  199.              move.l   d0,a0
  200.              tst.l    a0
  201.              beq      CreateExtIO9
  202.              move.b   #NT_MESSAGE,IO+MN+LN_TYPE(a0)
  203.              move.w   d2,IO+MN_LENGTH(a0)
  204.              move.l   a2,IO+MN_REPLYPORT(a0)
  205. CreateExtIO9         move.l   a0,d0
  206.              movem.l  (sp)+,a2/d2
  207.              rts
  208.  
  209. ;
  210. ;             Free a DeviceBlock
  211. ;
  212. ;             a0: DeviceBlock ptr
  213. ;
  214. FreeDeviceBlock      movem.l  a2,-(sp)
  215.              move.l   a0,a2
  216.              tst.l    a0
  217.              beq      FreeDeviceBlock9
  218.              move.l   IO+MN_REPLYPORT(a2),d0
  219.              beq      FreeDeviceBlock8
  220.              move.l   d0,a0
  221.              bsr      DeletePort
  222. FreeDeviceBlock8     move.l   a2,a0
  223.              bsr      DeleteExtIO
  224. FreeDeviceBlock9     movem.l  (sp)+,a2
  225.              rts
  226.  
  227. ;
  228. ;             Get a DeviceBlock
  229. ;
  230. ;             d0.w: Size
  231. ;             -> d0 = DeviceBlock ptr (=0 if fail)
  232. ;
  233. GetDeviceBlock         movem.l  d2-d3,-(sp)
  234.              move.l   d0,d2
  235.              clr.l    d0
  236.              move.l   d0,a0
  237.              bsr      CreatePort
  238.              move.l   d0,d3
  239.              beq      GetDeviceBlock9
  240.              move.l   d3,a0
  241.              move.l   d2,d0
  242.              bsr      CreateExtIO
  243.              tst.l    d0
  244.              bne      GetDeviceBlock9
  245.              move.l   d3,a0
  246.              bsr      DeletePort
  247.              clr.l    d0
  248. GetDeviceBlock9      movem.l  (sp)+,d2-d3
  249.              rts
  250.  
  251.  
  252. ;
  253. ;             Close Audio channels
  254. ;
  255. ;             a0: hard_port
  256. ;
  257. close_audio_channels
  258.    XDEF close_audio_channels
  259.              movem.l  a2-a3,-(sp)
  260.              move.l   a0,a2
  261.              move.l   hp_port(a2),a3
  262.              move.l   hp_intnum(a2),d0
  263.              move.l   hp_old_interrupt(a2),a1
  264.              CALLEXEC SetIntVector
  265.              move.l   IOAudio+IO+MN_REPLYPORT(a3),d0
  266.              beq      close_audio_channel1
  267.              move.l   d0,a0
  268.              bsr      DeletePort
  269. close_audio_channel1 tst.l    IOAudio+IO_DEVICE(a3)
  270.              beq      close_audio_channel2
  271.              move.l   a3,a1
  272.              CALLEXEC CloseDevice
  273. close_audio_channel2 move.l   a3,a0
  274.              bsr      DeleteExtIO
  275.              movem.l  (sp)+,a2-a3
  276.              rts
  277.  
  278. ;
  279. ;             Open Audio channels
  280. ;
  281. ;             a0: hard_port
  282. ;             -> d0.l = 0 if fail, 1 if ok
  283. ;
  284. open_audio_channels
  285.    XDEF  open_audio_channels
  286.              movem.l  a2-a3,-(sp)
  287.              move.l   a0,a2
  288.              clr.l    d0
  289.              move.l   d0,a1
  290.              CALLEXEC FindTask
  291.              move.l   d0,hp_task(a2)
  292.              move.l   #ioa_SIZEOF,d0
  293.              bsr      GetDeviceBlock
  294.              move.l   d0,hp_port(a2)
  295.              beq      open_audio_channels9
  296.              move.l   d0,a3
  297.              clr.l    d0
  298.              move.l   IOAudio+IO+MN_REPLYPORT(a3),a0
  299.              move.b   MP_SIGBIT(a0),d0
  300.              move.l   d0,hp_signal(a2)
  301.              btst.b   #AUFB_16BITS,hp_flags(a2)
  302.              beq      open_audio_channels1
  303.              lea      AU_AllChannels,a1
  304.              moveq.l  #1,d1
  305.              bra      open_audio_channels2
  306. open_audio_channels1 lea      AU_LRChannels,a1
  307.              moveq.l  #4,d1
  308. open_audio_channels2 move.l   a1,ioa_Data(a3)
  309.              move.l   d1,ioa_Length(a3)
  310.              move.b   #AUDIO_PRI,IOAudio+IO+MN+LN_PRI(a3)
  311.              move.l   a3,a1
  312.              lea      AU_DEVICE_NAME,a0
  313.              moveq.l  #0,d0
  314.              moveq.l  #0,d1
  315.              CALLEXEC OpenDevice
  316.              tst.b    d0
  317.              bne      open_audio_channels8    ; Open error
  318.              move.l   IOAudio+IO_UNIT(a3),hp_channels_bitmap(a2)
  319.              move.l   a2,a1
  320.              bsr      @ASM_audio_init
  321.              lea      hp_audio_interrupt(a2),a1
  322.              move.b   #NT_INTERRUPT,IS+LN_TYPE(a1)
  323.              move.b   #0,IS+LN_PRI(a1)
  324.              lea      AU_PORT_NAME,a0
  325.              move.l   a0,IS+LN_NAME(a1)
  326.              move.l   a2,IS_DATA(a1)
  327.              lea      @ASM_audio_handler,a0
  328.              move.l   a0,IS_CODE(a1)
  329.              move.l   hp_intnum(a2),d0
  330.              CALLEXEC SetIntVector
  331.              move.l   d0,hp_old_interrupt(a2)
  332.              moveq.l  #1,d0
  333.              bra      open_audio_channels9
  334. open_audio_channels8 move.l   a3,a0
  335.              bsr      FreeDeviceBlock
  336.              clr.l    hp_port(a2)
  337.              clr.l    d0
  338. open_audio_channels9 movem.l  (sp)+,a2-a3
  339.              rts
  340.  
  341. ;
  342. ;             Delete Audio port
  343. ;
  344. ;             a0: audio_port
  345. ;
  346. delete_audio_port
  347.    XDEF  delete_audio_port
  348.              movem.l  d2-d3/a2-a4,-(sp)
  349.              tst.l    a0
  350.              beq      delete_audio_port9
  351.              move.l   a0,a2
  352.              move.l   au_hard_port(a2),a3
  353.              tst.l    a3
  354.              beq      delete_audio_port8
  355.              ; free USER input buffers
  356.              move.l   a3,a0
  357.              bsr      free_input_buffers
  358.              ; free mixing buffer
  359.              move.l   a3,a0
  360.              bsr      free_mixing_buffer
  361.              ; free audio buffers
  362.              clr.l    d4
  363. delete_audio_port3   move.w   d4,d0
  364.              move.l   a3,a0
  365.              bsr      free_audio_buffer
  366.              addq.w   #1,d4
  367.              cmp.w    #2,d4
  368.              blt.s    delete_audio_port3
  369.              ; free hard port
  370.              move.l   a3,a1
  371.              move.l   #hp_sizeof,d0
  372.              CALLEXEC FreeMem
  373. delete_audio_port8   ; free audio port
  374.              move.l   a2,a1
  375.              move.l   #au_sizeof,d0
  376.              CALLEXEC FreeMem
  377. delete_audio_port9   movem.l  (sp)+,d2-d3/a2-a4
  378.              rts
  379.  
  380. ;             Free the USER input buffers
  381. ;
  382. ;             a0.l  = hard_port *
  383. ;
  384. free_input_buffers
  385.    XDEF  free_input_buffers
  386.              movem.l  d2/a2/a6,-(sp)
  387.              move.l   a0,a2
  388.              move.l   hp_wave_max_length(a2),d2
  389.              beq.s    free_input_buffers9
  390.              btst.b   #AUFB_16BITS,hp_flags(a2)
  391.              beq.s    free_input_buffers0
  392.              add.l    d2,d2             ; 16-bit buffers
  393. free_input_buffers0  move.l   hp_input_l_wave(a2),a1
  394.              tst.l    a1
  395.              beq.s    free_input_buffers1
  396.              move.l   d2,d0
  397.              CALLEXEC FreeMem
  398.              clr.l    hp_input_l_wave(a2)
  399. free_input_buffers1  move.l   hp_input_r_wave(a2),a1
  400.              tst.l    a1
  401.              beq.s    free_input_buffers9
  402.              move.l   d2,d0
  403.              CALLEXEC FreeMem
  404.              clr.l    hp_input_r_wave(a2)
  405. free_input_buffers9  clr.l    hp_wave_max_length(a2)
  406.              movem.l  (sp)+,d2/a2/a6
  407.              rts
  408.  
  409. ;             Allocate the input buffers
  410. ;
  411. ;             d0.l  = input sample max length
  412. ;             a0.l  = hard_port *
  413. ;             -> d0.l = 0 if failure
  414. ;
  415. allocate_input_buffers
  416.    XDEF  allocate_input_buffers
  417.              movem.l  d2-d3/a2/a6,-(sp)
  418.              move.l   a0,a2              ; a2 = hard_port *
  419.              move.l   d0,d2
  420.              move.l   d0,hp_wave_max_length(a2)
  421.              btst.b   #AUFB_16BITS,hp_flags(a2)
  422.              beq.s    allocate_input_buff1    ; 8-bit sample
  423.              add.l    d2,d2
  424. allocate_input_buff1 move.l   #MEMF_PUBLIC|MEMF_CLEAR,d3
  425.              move.l   d2,d0
  426.              move.l   d3,d1
  427.              CALLEXEC AllocMem
  428.              tst.l    d0
  429.              beq      allocate_input_buff6    ; memory error
  430.              move.l   d0,hp_input_l_wave(a2)
  431.              btst.b   #AUFB_STEREO,hp_flags(a2)
  432.              beq      allocate_input_buff2
  433.              move.l   d2,d0
  434.              move.l   d3,d1
  435.              CALLEXEC AllocMem
  436.              tst.l    d0
  437.              beq      allocate_input_buff6    ; memory error
  438.              move.l   d0,hp_input_r_wave(a2)
  439. allocate_input_buff2 moveq.l  #-1,d0
  440.              bra.s    allocate_input_buff9
  441. allocate_input_buff6 move.l   a2,a0
  442.              bsr      free_input_buffers
  443.              clr.l    d0
  444. allocate_input_buff9 movem.l  (sp)+,d2-d3/a2/a6
  445.              rts
  446.  
  447.  
  448.  
  449. ;             Free the mixing buffer
  450. ;
  451. ;             a0.l  = hard_port *
  452. ;
  453. free_mixing_buffer
  454.    XDEF  free_mixing_buffer
  455.              movem.l  a2/a6,-(sp)
  456.              move.l   a0,a2
  457.              move.l   hp_mixing_buffer(a2),a1
  458.              tst.l    a1
  459.              beq.s    free_mixing_buffer9
  460.              move.l   hp_mixing_max_size(a2),d0
  461.              CALLEXEC FreeMem
  462.              clr.l    hp_mixing_buffer(a2)
  463. free_mixing_buffer9  clr.l    hp_mixing_max_size(a2)
  464.              movem.l  (sp)+,a2/a6
  465.              rts
  466.  
  467. ;             (Re)Allocate the mixing buffer if necessary
  468. ;
  469. ;             d0.l  = mixing sample length
  470. ;             a0.l  = hard_port *
  471. ;             -> d0.l = 0 if failure
  472. ;
  473. allocate_mixing_buffer
  474.    XDEF  allocate_mixing_buffer
  475.              movem.l  d2/d5/a3/a6,-(sp)
  476.              move.l   a0,a3           ; a3 = hard_port *
  477.              move.b   hp_flags(a3),d5
  478.              btst     #AUFB_16BITS,d5
  479.              beq.s    allocate_mixing_buf1 ; 8-bit sample
  480.              add.l    d0,d0
  481. allocate_mixing_buf1 cmp.l    hp_mixing_max_size(a3),d0
  482.              ble      allocate_mixing_buf8 ; Actual mixing buffer is ok
  483.              move.l   d0,d2           ; d2 = New mixing size
  484.              move.l   a3,a0
  485.              bsr      free_mixing_buffer
  486.              move.l   d2,d0
  487.              move.l   #MEMF_PUBLIC,d1
  488.              CALLEXEC AllocMem
  489.              tst.l    d0
  490.              beq.s    allocate_mixing_buf6 ; memory error
  491.              move.l   d0,hp_mixing_buffer(a3)
  492.              move.l   d2,hp_mixing_max_size(a3)
  493.              bra.s    allocate_mixing_buf8
  494. allocate_mixing_buf6 clr.l    d0
  495.              bra.s    allocate_mixing_buf9
  496. allocate_mixing_buf8 moveq.l  #-1,d0
  497. allocate_mixing_buf9 movem.l  (sp)+,d2/d5/a3/a6
  498.              rts
  499.  
  500.  
  501.  
  502. ;             Free one audio buffer
  503. ;
  504. ;             d0.w  = buffer number
  505. ;             a0.l  = hard_port *
  506. ;
  507. free_audio_buffer
  508.    XDEF  free_audio_buffer
  509.              movem.l  d2-d3/a2/a6,-(sp)
  510.              move.l   (hp_wave_max_size,a0,d0.w*4),d2  ; Actual size
  511. ;              tst.l    d2
  512. ;              beq      free_audio_buffer9
  513.              clr.l    (hp_wave_max_size,a0,d0.w*4)  ; New size is 0
  514.              lea      (hp_l_wave_h,a0,d0.w*4),a2 ; first buffer ptr
  515.              moveq.w  #4-1,d3             ; 4 buffer to free
  516. free_audio_buffer1   move.l   (a2),a1
  517.              tst.l    a1
  518.              beq.s    free_audio_buffer2   ; This buffer is free
  519.              move.l   d2,d0
  520.              CALLEXEC FreeMem
  521.              clr.l    (a2)
  522. free_audio_buffer2   addq.l   #2*4,a2
  523.              dbra     d3,free_audio_buffer1
  524. free_audio_buffer9
  525.              movem.l  (sp)+,d2-d3/a2/a6
  526.              rts
  527.  
  528. ;             (Re)Allocate one audio buffer if necessary
  529. ;
  530. ;             d0.l  = sample size
  531. ;             d1.w  = buffer number
  532. ;             a0.l  = hard_port *
  533. ;             -> d0.l = 0 if failure
  534. ;
  535. allocate_audio_buffer
  536.    XDEF  allocate_audio_buffer
  537.              movem.l  d2-d5/a2-a3/a6,-(sp)
  538.              move.l   d0,d2           ; d2 = sample size
  539.              move.l   d1,d3           ; d3 = # buffer
  540.              move.l   #MEMF_CHIP,d4       ; d4 = memory type
  541.              move.l   a0,a3           ; a3 = hard_port *
  542.              move.l   (hp_wave_max_size,a3,d3.w*4),d0  ; Actual size
  543.              cmp.l    d0,d2
  544.              ble      allocate_audio_buff8 ; Actual size is ok
  545.              move.l   d3,d0
  546.              move.l   a3,a0
  547.              bsr      free_audio_buffer    ; Free this audio buffer
  548.              move.l   d2,(hp_wave_max_size,a3,d3.w*4)  ; New size
  549.              move.b   hp_flags(a3),d5
  550.              move.l   d2,d0
  551.              move.l   d4,d1
  552.              CALLEXEC AllocMem
  553.              tst.l    d0
  554.              beq      allocate_audio_buff6     ; memory error
  555.              move.l   d0,(hp_l_wave_h,a3,d3.w*4)
  556.              btst     #AUFB_16BITS,d5
  557.              beq      allocate_audio_buff2     ; 8-bit only !
  558.              move.l   d2,d0
  559.              move.l   d4,d1
  560.              CALLEXEC AllocMem
  561.              tst.l    d0
  562.              beq      allocate_audio_buff6     ; memory error
  563.              move.l   d0,(hp_l_wave_l,a3,d3.w*4)
  564. allocate_audio_buff2 btst     #AUFB_STEREO,d5         ; mono samples !
  565.              beq      allocate_audio_buff3
  566.              move.l   d2,d0
  567.              move.l   d4,d1
  568.              CALLEXEC AllocMem
  569.              tst.l    d0
  570.              beq      allocate_audio_buff6     ; memory error
  571.              move.l   d0,(hp_r_wave_h,a3,d3.w*4)
  572.              btst     #AUFB_16BITS,d5         ; 8-bit only !
  573.              beq      allocate_audio_buff3
  574.              move.l   d2,d0
  575.              move.l   d4,d1
  576.              CALLEXEC AllocMem
  577.              tst.l    d0
  578.              beq      allocate_audio_buff6     ; memory error
  579.              move.l   d0,(hp_r_wave_l,a3,d3.w*4)
  580. allocate_audio_buff3 bra.s    allocate_audio_buff8
  581. allocate_audio_buff6              ; memory error -> free allocated buffers
  582.              move.l   d3,d0
  583.              move.l   a3,a0
  584.              bsr      free_audio_buffer    ; Free this audio buffer
  585.              clr.l    d0
  586.              bra.s    allocate_audio_buff9
  587. allocate_audio_buff8 moveq.l  #-1,d0
  588. allocate_audio_buff9 movem.l  (sp)+,d2-d5/a2-a3/a6
  589.              rts
  590.  
  591. ;
  592. ;             New Audio port
  593. ;
  594. ;             d0.b  : flags
  595. ;             d1.l  : buffer_size
  596. ;             -> d0.l = audio_port (=NULL if fail)
  597. ;
  598. new_audio_port
  599.    XDEF  new_audio_port
  600.              movem.l  d2-d5/a2-a4,-(sp)
  601.              move.l   d0,d2
  602.              move.l   d1,d3
  603.              tst.l    d1
  604.              ble      new_audio_port8    ; <= 0
  605.              cmp.l    #$20000,d1
  606.              bge      new_audio_port8    ; >= $20000
  607.              btst     #0,d1
  608.              bne      new_audio_port8    ; odd buffer_size !
  609.              move.l   #au_sizeof,d0
  610.              move.l   #MEMF_PUBLIC|MEMF_CLEAR,d1
  611.              CALLEXEC AllocMem
  612.              tst.l    d0
  613.              beq      new_audio_port8    ; memory error
  614.              move.l   d0,a2
  615.              move.l   #hp_sizeof,d0
  616.              move.l   #MEMF_PUBLIC|MEMF_CLEAR,d1
  617.              CALLEXEC AllocMem
  618.              tst.l    d0
  619.              beq      new_audio_port6    ; memory error
  620.              move.l   d0,a3
  621.              move.l   a3,au_hard_port(a2)
  622. ;              move.l   d3,hp_wave_max_length(a3)  (#5 set by allocate_input_buffers)
  623.              move.b   d2,hp_flags(a3)
  624.              ; default values
  625.              moveq.l  #23,d0
  626.              move.l   d0,hp_current_period(a3)
  627.              moveq.w  #64,d0
  628.              move.w   d0,hp_l_vol(a3)
  629.              move.w   d0,hp_r_vol(a3)
  630.              ;
  631.              ; allocate USER input buffers     #5
  632.              ;
  633.              move.l   a3,a0
  634.              move.l   d3,d0
  635.              bsr      allocate_input_buffers
  636.              tst.l    d0
  637.              beq      new_audio_port6       ; memory error
  638.              move.l   hp_input_l_wave(a3),au_l_wave(a2)
  639.              move.l   hp_input_r_wave(a3),au_r_wave(a2)
  640.              ;
  641.              ; allocate audio buffers         #5
  642.              ;
  643.              clr.l    d4
  644. new_audio_port1      move.l   d3,d0           ; sample size
  645.              move.w   d4,d1           ; buffer number
  646.              move.l   a3,a0           ; hard_port *
  647.              bsr      allocate_audio_buffer
  648.              tst.l    d0
  649.              beq      new_audio_port6       ; memory error
  650.              addq.w   #1,d4
  651.              cmp.w    #2,d4           ; double buffering
  652.              blt.s    new_audio_port1
  653.              clr.l    hp_active_wave(a3)
  654.  
  655.              move.l   a2,d0
  656.              bra      new_audio_port9
  657. new_audio_port6      move.l   a2,a0
  658.              bsr      delete_audio_port
  659. new_audio_port8      clr.l    d0
  660. new_audio_port9      movem.l  (sp)+,d2-d5/a2-a4
  661.              rts
  662.  
  663.  
  664. ;
  665. ;             Process an input wave
  666. ;
  667. ;             a0: audio_port
  668. ;             -> d0.l = 0 if failure
  669. ;
  670. process_wave
  671.              movem.l  d2-d5/a2-a4,-(sp)
  672.              move.l   a0,a3              ; a3 = audio_port
  673.              move.l   au_hard_port(a3),a4     ; a4 = hard_port
  674.              move.l   hp_active_wave(a4),d3
  675.              move.l   au_wave_length(a3),d5   ; = sample length
  676.              beq      process_wave85          ; No sample -> no process
  677.              move.l   hp_current_period(a4),d0
  678.              move.l   d0,(hp_wave_period,a4,d3.w*4)
  679.              btst.b   #AUFB_MIXING,au_flags(a3)
  680.              beq      process_wave0         ; no mixing
  681.              move.l   d5,d2             ; d2.l = wave_length
  682.              move.l   hp_input_frequency(a4),d0
  683.              move.l   hp_output_frequency(a4),d1
  684.              bsr      audio_mix_size
  685.              move.l   d0,hp_mixing_length(a4)
  686.              move.l   d0,d5             ; = new sample length
  687.              beq      process_wave8         ; failure
  688.              move.l   a4,a0             ; and d0.l = mixing length
  689.              bsr      allocate_mixing_buffer
  690.              tst.l    d0
  691.              beq      process_wave8         ; failure
  692. process_wave0         move.l   d5,(hp_wave_length,a4,d3.w*4) ; = sample length
  693.              ; Allocate audio buffers if necessary
  694.              move.l   d5,d0              ; out sample length
  695.              move.l   d3,d1              ; buffer number
  696.              move.l   a4,a0              ; hard_port *
  697.              bsr      allocate_audio_buffer
  698.              tst.l    d0
  699.              beq      process_wave8          ; allocate failure
  700.              btst.b   #AUFB_16BITS,hp_flags(a4)
  701.              bne      process_wave5          ; 16-bit process
  702.              ;
  703.              ; 8-bit samples processing
  704.              ;
  705.              ; 1) Mix Mono or Left sample ?
  706.              move.l   au_l_wave(a3),a0           ; input sample
  707.              tst.l    a0
  708.              beq      process_wave2
  709.              btst.b   #AUFB_MIXING,au_flags(a3)
  710.              beq      process_wave1         ; no mixing
  711.              move.l   hp_mixing_buffer(a4),a1    ; BYTE *output_sample
  712.              move.l   hp_input_frequency(a4),d0
  713.              move.l   hp_output_frequency(a4),d1
  714.              move.l   d5,d2
  715.              bsr      @ASM_audio_8_mix
  716.              move.l   hp_mixing_buffer(a4),a0
  717. process_wave1         ; 2) Copy processed wave to audio buffers
  718.              move.l   (hp_l_wave_h,a4,d3.w*4),a1 ; audio buffer
  719.              tst.l    a1
  720.              beq      process_wave2
  721.              move.l   d5,d0             ; #bytes to copy
  722.              CALLEXEC CopyMem
  723. process_wave2         ; 3) Mix Right or Stereo sample ?
  724.              btst.b   #AUFB_STEREO,hp_flags(a4)
  725.              beq      process_wave3         ; Mono sample
  726.              move.l   au_r_wave(a3),a0           ; input sample
  727.              tst.l    a0
  728.              beq      process_wave4
  729.              btst.b   #AUFB_MIXING,au_flags(a3)
  730.              beq      process_wave3         ; no mixing
  731.              move.l   hp_mixing_buffer(a4),a1    ; BYTE *output_sample
  732.              move.l   hp_input_frequency(a4),d0
  733.              move.l   hp_output_frequency(a4),d1
  734.              move.l   d5,d2
  735.              bsr      @ASM_audio_8_mix
  736.              move.l   hp_mixing_buffer(a4),a0
  737. process_wave3         ; 4) Copy processed wave to audio buffers
  738.              move.l   (hp_r_wave_h,a4,d3.w*4),a1 ; audio buffer
  739.              tst.l    a1
  740.              beq      process_wave4
  741.              move.l   d5,d0             ; #bytes to copy
  742.              CALLEXEC CopyMem
  743. process_wave4         moveq.l  #-1,d0
  744.              bra      process_wave9
  745.              ;
  746. process_wave5         ; 16-bit samples processing
  747.              ;
  748.              ; 1) Mix Mono or Left sample ?
  749.              move.l   au_l_wave(a3),a0           ; input sample
  750.              tst.l    a0
  751.              beq      process_wave65
  752.              btst.b   #AUFB_MIXING,au_flags(a3)
  753.              beq      process_wave61         ; no mixing
  754.              move.l   hp_mixing_buffer(a4),a1    ; BYTE *output_sample
  755.              move.l   hp_input_frequency(a4),d0
  756.              move.l   hp_output_frequency(a4),d1
  757.              move.l   d5,d2
  758.              bsr      @ASM_audio_16_mix
  759.              move.l   hp_mixing_buffer(a4),a0
  760. process_wave61         ; 2) Split 16-bit sample to 8-bit audio buffers
  761.              move.l   d5,d0
  762.              move.l   (hp_l_wave_h,a4,d3.w*4),a1
  763.              move.l   (hp_l_wave_l,a4,d3.w*4),a2
  764.              move.w   hp_l_vol(a4),d1
  765.              bsr      @ASM_audio_split_vol
  766. process_wave65         ; 3) Mix Right or Stereo sample ?
  767.              btst.b   #AUFB_STEREO,hp_flags(a4)
  768.              beq      process_wave75         ; Mono sample
  769.              move.l   au_r_wave(a3),a0           ; input sample
  770.              tst.l    a0
  771.              beq      process_wave75
  772.              btst.b   #AUFB_MIXING,au_flags(a3)
  773.              beq      process_wave71         ; no mixing
  774.              move.l   hp_mixing_buffer(a4),a1    ; BYTE *output_sample
  775.              move.l   hp_input_frequency(a4),d0
  776.              move.l   hp_output_frequency(a4),d1
  777.              move.l   d5,d2
  778.              bsr      @ASM_audio_16_mix
  779.              move.l   hp_mixing_buffer(a4),a0
  780. process_wave71         ; 4) Split 16-bit sample to 8-bit audio buffers
  781.              move.l   d5,d0
  782.              move.l   (hp_r_wave_h,a4,d3.w*4),a1
  783.              move.l   (hp_r_wave_l,a4,d3.w*4),a2
  784.              move.w   hp_r_vol(a4),d1
  785.              bsr      @ASM_audio_split_vol
  786. process_wave75         moveq.l  #-1,d0
  787.              bra      process_wave9
  788. process_wave8         clr.l    d0
  789.              bra      process_wave9
  790. process_wave85         clr.l    (hp_wave_length,a4,d3.w*4) ; sample length = 0
  791.              moveq.l  #-1,d0
  792. process_wave9         movem.l  (sp)+,d2-d5/a2-a4
  793.              rts
  794.  
  795. ;
  796. ;             Write to Audio port
  797. ;
  798. ;             a0: audio_port
  799. ;
  800. @AU_write
  801. AU_write         movem.l  d2-d5/a2-a4,-(sp)
  802.              tst.l    a0
  803.              beq      AU_write9
  804.              move.l   a0,a3
  805.              move.l   au_hard_port(a3),a4     ; a4 = hard_port
  806.              clr.l    d2
  807.              move.b   au_flags(a3),d2
  808.              btst     #AUFB_FREQ,d2
  809.              beq      AU_write1
  810.              move.l   au_frequency(a3),d0
  811.              move.l   d0,hp_input_frequency(a4)  ; #5
  812.              btst     #AUFB_MIXING,d2         ; #5
  813.              beq      AU_write0          ; #5
  814.              move.l   au_mixing_frequency(a3),d0 ; #5
  815. AU_write0         move.l   d0,hp_output_frequency(a4) ; #5
  816.              bsr      calculate_period
  817.              move.l   d0,hp_current_period(a4)
  818. AU_write1         btst     #AUFB_VOL,d2
  819.              beq      AU_write2
  820.              move.w   au_l_vol(a3),hp_l_vol(a4)
  821.              move.w   au_r_vol(a3),hp_r_vol(a4)
  822. AU_write2         btst     #AUFB_FILTER,d2
  823.              beq      AU_write3
  824.              bclr     #AUFB_FILTER,hp_flags(a4)  ; ???
  825.              tst.b    au_filter_on(a3)
  826.              beq      AU_write3
  827.              bset     #AUFB_FILTER,hp_flags(a4)  ; ???
  828. AU_write3         move.b   au_command(a3),d3
  829.              cmp.b    #AUC_CONTROL,d3
  830.              bne      AU_write4
  831. ;              btst     #AUFB_FREQ,d2
  832. ;              move.l   a4,a1
  833. ;              bsr      @ASM_audio_per
  834. AU_write31         btst     #AUFB_VOL,d2
  835.              beq      AU_write32
  836.              move.l   a4,a1
  837.              bsr      @ASM_audio_vol
  838. AU_write32         btst     #AUFB_FILTER,d2
  839.              beq      AU_write33
  840.              move.l   a4,a1
  841.              bsr      @ASM_audio_filter
  842. AU_write33         bra      AU_write9
  843. AU_write4         cmp.b    #AUC_WRITE,d3
  844.              bne      AU_write5
  845.              move.l   a3,a0              ; a0 = audio_port *
  846.              bsr      process_wave          ; #5
  847.              tst.l    d0
  848.              beq      AU_write9           ; process_wave error
  849.              move.l   a4,a1
  850.              bsr      @ASM_audio_write
  851.              move.l   hp_active_wave(a4),d3
  852.              bchg     #0,d3
  853.              move.l   d3,hp_active_wave(a4)   ; active_wave ^= 1
  854.              btst.b   #AUFB_NOWAIT,au_flags(a3)
  855.              bne      AU_write42
  856.              clr.l    d0
  857.              move.l   hp_signal(a4),d1
  858.              bset     d1,d0
  859.              CALLEXEC Wait
  860. AU_write42
  861.              ; #5: if no input buffers, use audio buffers for USER
  862. ;              btst     #AUFB_16BITS,d2
  863. ;              tst.l    hp_input_l_wave(a4)
  864. ;              bne      AU_write43        ; Ok, left input buffer exist
  865. ;              move.l   (hp_l_wave_h,a4,d3.w*4),au_l_wave(a3)
  866. ;AU_write43          tst.l    hp_input_r_wave(a4)
  867. ;              bne      AU_write44        ; Ok, Right input buffer exist
  868. ;              move.l   (hp_r_wave_h,a4,d3.w*4),au_r_wave(a3)
  869. AU_write44         bra      AU_write9
  870. AU_write5         cmp.b    #AUC_STOP,d3
  871.              bne      AU_write6
  872.              move.l   a4,a1
  873.              bsr      @ASM_audio_stop
  874.              bra      AU_write9
  875. AU_write6         cmp.b    #AUC_CONTINUE,d3
  876.              bne      AU_write9
  877.  
  878. AU_write9         movem.l  (sp)+,d2-d5/a2-a4
  879.              rts
  880.  
  881. ;
  882. ;             Close an Audio port
  883. ;
  884. ;             a0 = audio_port
  885. ;
  886. @AU_close
  887. AU_close         movem.l  a2-a3,-(sp)
  888.              tst.l    a0
  889.              beq      AU_close9
  890.              move.l   a0,a2
  891.              move.l   au_hard_port(a2),a3
  892.              move.l   a3,a1
  893.              bsr      @ASM_audio_stop
  894.              move.l   a3,a0
  895.              bsr      close_audio_channels
  896.              move.l   a2,a0
  897.              bsr      delete_audio_port
  898. AU_close9         movem.l  (sp)+,a2-a3
  899.              rts
  900.  
  901. ;
  902. ;             Open an Audio port
  903. ;
  904. ;             d0.b  : flags
  905. ;             d1.l  : buffer_size
  906. ;             -> d0.l = audio_port or NULL if fail
  907. ;
  908. @AU_open
  909. AU_open          movem.l  a2-a3,-(sp)
  910.              bsr      new_audio_port
  911.              tst.l    d0
  912.              beq      AU_open9
  913.              move.l   d0,a2
  914.              move.l   au_hard_port(a2),a3
  915.              move.l   a3,a0
  916.              bsr      open_audio_channels
  917.              tst.l    d0
  918.              bne      AU_open1
  919.              move.l   a2,a0
  920.              bsr      delete_audio_port
  921.              clr.l    d0
  922.              bra      AU_open9
  923. AU_open1         move.l   hp_signal(a3),d0
  924.              move.b   d0,au_signal(a2)
  925.              move.l   a2,d0
  926. AU_open9         movem.l  (sp)+,a2-a3
  927.              rts
  928.  
  929.  
  930. ;             Audio Split 16bits -> 2x8bits for 14bit audio
  931. ;
  932. ;             a0 = WORD    *Wave16bits
  933. ;             a1 = BYTE    *WaveH8bits
  934. ;             a2 = BYTE    *WaveL8bits
  935. ;             d0 = ULONG  Wave16Length
  936. ;
  937. @ASM_audio_split
  938.              movem.l  d0-d7/a0-a2,-(sp)
  939.              move.w   #128,d7
  940.              move.w   #$FF00,d6
  941.              move.w   #$FF,d5
  942.              lsr.l    #1,d0
  943.              subq.l   #1,d0
  944. ASM_audio_split1
  945.              move.w   (a0)+,d1
  946.              move.w   d1,d2
  947.              add.w    d7,d1
  948.              bvs.s    ASM_audio_split2
  949.              and.w    d6,d1
  950.              asr.b    #2,d2
  951.              lsl.w    #8,d2
  952. ASM_audio_split3
  953.              move.w   (a0)+,d3
  954.              move.w   d3,d4
  955.              add.w    d7,d3
  956.              bvs.s    ASM_audio_split4
  957.              lsr.w    #8,d3
  958.              asr.b    #2,d4
  959.              and.w    d5,d4
  960. ASM_audio_split5
  961.              or.w     d3,d1
  962.              move.w   d1,(a1)+
  963.              or.w     d4,d2
  964.              move.w   d2,(a2)+
  965.              dbra     d0,ASM_audio_split1
  966.              movem.l  (sp)+,d0-d7/a0-a2
  967.              rts
  968. ASM_audio_split2
  969.              move.w   #$7F00,d1
  970.              move.w   d1,d2
  971.              bra.s    ASM_audio_split3
  972. ASM_audio_split4
  973.              moveq.w #$7F,d3
  974.              move.w  d1,d4
  975.              bra.s   ASM_audio_split5
  976.  
  977.  
  978.  
  979. ; #5             Audio Split 16bits + Volume set -> 2x8bits for 14bit audio
  980. ;
  981. ;             a0 = WORD    *Wave16bits
  982. ;             a1 = BYTE    *WaveH8bits
  983. ;             a2 = BYTE    *WaveL8bits
  984. ;             d0 = ULONG  Wave16Length
  985. ;             d1.w = Volume (64 = Normal)
  986. ;
  987. @ASM_audio_split_vol
  988.              cmp.w    #64,d1           ; If volume is normal, use
  989.              beq      @ASM_audio_split       ; ASM_audio_split instead
  990.              movem.l  d0-d7/a0-a3,-(sp)
  991.              move.w   d1,d7
  992.              lea.l    128,a3
  993.              move.w   #$FF00,d6
  994.              move.w   #$FF,d5
  995.              lsr.l    #1,d0
  996.              subq.l   #1,d0
  997. ASM_audio_split_vol1
  998.              move.w   (a0)+,d1
  999.              muls.w   d7,d1
  1000.              asr.l    #6,d1
  1001.              move.w   d1,d2
  1002.              add.w    a3,d1
  1003.              bvs.s    ASM_audio_split_vol2
  1004.              and.w    d6,d1
  1005.              asr.b    #2,d2
  1006.              lsl.w    #8,d2
  1007. ASM_audio_split_vol3
  1008.              move.w   (a0)+,d3
  1009.              muls.w   d7,d3
  1010.              asr.l    #6,d3
  1011.              move.w   d3,d4
  1012.              add.w    a3,d3
  1013.              bvs.s    ASM_audio_split_vol4
  1014.              lsr.w    #8,d3
  1015.              asr.b    #2,d4
  1016.              and.w    d5,d4
  1017. ASM_audio_split_vol5
  1018.              or.w     d3,d1
  1019.              move.w   d1,(a1)+
  1020.              or.w     d4,d2
  1021.              move.w   d2,(a2)+
  1022.              dbra     d0,ASM_audio_split_vol1
  1023.              movem.l  (sp)+,d0-d7/a0-a3
  1024.              rts
  1025. ASM_audio_split_vol2
  1026.              move.w   #$7F00,d1
  1027.              move.w   d1,d2
  1028.              bra.s    ASM_audio_split_vol3
  1029. ASM_audio_split_vol4
  1030.              moveq.w #$7F,d3
  1031.              move.w  d1,d4
  1032.              bra.s   ASM_audio_split_vol5
  1033.  
  1034.  
  1035. AUDIO_16_MIX_SHIFT   equ      14
  1036.  
  1037. ; #5             Audio mix 8-bit sample at freq f1 -> 8-bit sample freq f2
  1038. ;
  1039. ;             a0 = BYTE *input_sample
  1040. ;             a1 = BYTE *output_sample
  1041. ;             d0.l = input freq
  1042. ;             d1.l = output freq
  1043. ;             d2.l = output sample size
  1044. ;
  1045.  
  1046. @ASM_audio_8_mix
  1047.    XDEF  @ASM_audio_8_mix
  1048.              movem.l  d2-d7,-(sp)
  1049.  
  1050.              move.l   d2,d7           ; d7 = output sample size
  1051.              tst.w    d1
  1052.              beq      ASM_audio_8_mix9
  1053.              move.l   #1<<AUDIO_16_MIX_SHIFT,d6  ; d6 = t_max
  1054.              mulu.w   d6,d0
  1055.              divu.l   d1,d0
  1056.              move.l   d0,d5           ; d5 = t_inc
  1057.              move.l   d6,d4
  1058.              add.l    d4,d4           ; d4 = t_out = 2*t_max
  1059.              moveq.l  #AUDIO_16_MIX_SHIFT,d1
  1060. ASM_audio_8_mix1
  1061.              cmp.l    d6,d4
  1062.              blt.s    ASM_audio_8_mix2
  1063. ASM_audio_8_mix10    move.l   d3,d2           ; d2 = e0, d3 = e1
  1064.              move.b   (a0)+,d3
  1065.              ext.w    d3
  1066.              sub.l    d6,d4           ; t_out -= t_max
  1067.              cmp.l    d6,d4
  1068.              bge.s    ASM_audio_8_mix10
  1069. ASM_audio_8_mix2     move.w   d3,d0
  1070.              sub.w    d2,d0           ; e1-e0
  1071.              muls.w   d4,d0           ; (e1-e0) * t_out
  1072.              asr.l    d1,d0
  1073.              add.w    d2,d0           ; e0 + ((e1-e0) * t_out)>>14
  1074.              move.b   d0,(a1)+
  1075.              add.l    d5,d4           ; t_out += t_inc
  1076.              subq.l   #1,d7
  1077.              bne.s    ASM_audio_8_mix1
  1078. ASM_audio_8_mix9     movem.l  (sp)+,d2-d7
  1079.              rts
  1080.  
  1081.  
  1082.  
  1083.  
  1084. ; #6             Audio mix 16-bit sample at freq f1 -> 16-bit sample freq f2
  1085. ;
  1086. ;             a0 = WORD *input_sample
  1087. ;             a1 = WORD *output_sample
  1088. ;             d0.l = input freq
  1089. ;             d1.l = output freq
  1090. ;             d2.l = output sample size
  1091. ;
  1092. @ASM_audio_16_mix
  1093.    XDEF  @ASM_audio_16_mix
  1094.              movem.l  d2-d7,-(sp)
  1095.  
  1096.              move.l   d2,d7           ; d7 = output sample size
  1097.              tst.w    d1
  1098.              beq      ASM_audio_16_mix9
  1099.              move.l   #1<<AUDIO_16_MIX_SHIFT,d6  ; d6 = t_max
  1100.              mulu.w   d6,d0
  1101.              divu.l   d1,d0
  1102.              move.l   d0,d5           ; d5 = t_inc
  1103.              move.l   d6,d4
  1104.              add.l    d4,d4           ; d4 = t_out = 2*t_max
  1105.              moveq.l  #AUDIO_16_MIX_SHIFT,d1
  1106. ASM_audio_16_mix1
  1107.              cmp.l    d6,d4
  1108.              blt.s    ASM_audio_16_mix2
  1109. ASM_audio_16_mix10   move.l   d3,d2           ; d2 = e0, d3 = e1
  1110.              move.w   (a0)+,d3
  1111.              ext.l    d3
  1112.              sub.l    d6,d4           ; t_out -= t_max
  1113.              cmp.l    d6,d4
  1114.              bge.s    ASM_audio_16_mix10
  1115. ASM_audio_16_mix2    move.l   d3,d0
  1116.              sub.l    d2,d0           ; e1-e0
  1117.              muls.l   d4,d0           ; (e1-e0) * t_out
  1118.              asr.l    d1,d0
  1119.              add.l    d2,d0           ; e0 + ((e1-e0) * t_out)>>13
  1120.              move.w   d0,(a1)+
  1121.              add.l    d5,d4           ; t_out += t_inc
  1122.              subq.l   #1,d7
  1123.              bne.s    ASM_audio_16_mix1
  1124. ASM_audio_16_mix9    movem.l  (sp)+,d2-d7
  1125.              rts
  1126.  
  1127.  
  1128.  
  1129. ; #5             Audio mix sample size calculation
  1130. ;
  1131. ;             d0.l = input_freq
  1132. ;             d1.l = mixing_freq
  1133. ;             d2.l = wave_length: input sample size (0x20000 max)
  1134. ;             -> d0.l = mixing_length: output mixing sample size
  1135. ;
  1136. ;             Formula is :
  1137. ;             mixing_length = (wave_length * t_max) / t_inc
  1138. ;             t_max = 1<<AUDIO_16_MIX_SHIFT
  1139. ;             t_inc = (t_max * input_freq) / mixing_freq
  1140. ;
  1141. audio_mix_size
  1142.    XDEF audio_mix_size
  1143.              movem.l  d2-d3,-(sp)
  1144.              tst.l    d1
  1145.              beq      audio_mix_size9
  1146.              move.l   #1<<AUDIO_16_MIX_SHIFT,d3
  1147.              mulu.l   d3,d0
  1148.              divu.l   d1,d0         ; d0 = t_inc
  1149.              mulu.l   d3,d2
  1150. ;              add.l    d0,d2         ; Suppressed 24/07/1995
  1151.              divu.l   d0,d2
  1152. audio_mix_size9      move.l   d2,d0         ; d0 = mixing sample size
  1153.              and.b    #$FE,d0         ; Assume size to be even
  1154.              cmp.l    #$20000,d0     ; max size for audio dma's
  1155.              ble      audio_mix_size10
  1156.              move.l   #$20000,d0
  1157. audio_mix_size10     movem.l  (sp)+,d2-d3
  1158.              rts
  1159.  
  1160. ;             Audio init
  1161. ;
  1162. ;             a1 = struct hard_port *hport
  1163. ;
  1164. @ASM_audio_init
  1165.              movem.l  d2-d4,-(sp)
  1166.              lea      _custom,a0
  1167.              move.l   hp_channels_bitmap(a1),d1
  1168.              btst.b   #AUFB_16BITS,hp_flags(a1)
  1169.              bne.s    ASM_audio_ini5       ; 16 bits
  1170.              move.w   #aud0,d2
  1171.              btst     #0,d1
  1172.              bne.s    ASM_audio_ini1
  1173.              move.w   #aud3,d2
  1174. ASM_audio_ini1         move.w   d2,hp_l_channel_h(a1)
  1175.              move.w   #aud1,d2
  1176.              btst     #1,d1
  1177.              bne.s    ASM_audio_ini2
  1178.              move.w   #aud2,d2
  1179. ASM_audio_ini2         move.w   d2,hp_r_channel_h(a1)
  1180.              bra.s    ASM_audio_ini6
  1181. ASM_audio_ini5
  1182.              move.w   #aud0,hp_l_channel_h(a1)
  1183.              move.w   #aud1,hp_r_channel_h(a1)
  1184.              move.w   #aud2,hp_r_channel_l(a1)
  1185.              move.w   #aud3,hp_l_channel_l(a1)
  1186. ASM_audio_ini6
  1187.              move.w   #$00FF,hp_adkcon(a1) ; adkcon
  1188.              move.w   d1,d2           ; audena
  1189.              and.w    #$000F,d2
  1190.              move.w   d2,hp_audena(a1)
  1191.              move.w   d1,d2           ; intdis
  1192.              lsl.w    #7,d2
  1193.              and.w    #$0780,d2
  1194.              move.w   d2,hp_intdis(a1)
  1195.              clr.l    d2           ; intena (enable only 1 channel int)
  1196.              moveq.l  #7,d3           ; start int level
  1197.              moveq.w  #3-1,d4
  1198. ASM_audio_ini7
  1199.              lsr.l    #1,d1
  1200.              bcs.s    ASM_audio_ini8
  1201.              addq.l   #1,d3
  1202.              dbra     d4,ASM_audio_ini7
  1203. ASM_audio_ini8
  1204.              move.l   d3,hp_intnum(a1)
  1205.              bset     d3,d2
  1206.              bset     #15,d2
  1207.              move.w   d2,hp_intena(a1)
  1208.  
  1209.              movem.l  (sp)+,d2-d4
  1210.              bsr.w    @ASM_audio_stop
  1211.              rts
  1212.  
  1213. ;             Audio stop wave
  1214. ;
  1215. ;             a1 = struct hard_port *hport
  1216. ;
  1217. @ASM_audio_stop
  1218.              lea      _custom,a0
  1219.              clr.b    hp_playing(a1)    ; Audio stopped
  1220.              moveq.l  #0,d0
  1221.              move.w   hp_l_channel_h(a1),d1
  1222.              move.w   d0,(AU_VOL,a0,d1.w)      ; Volume -> 0
  1223.              move.w   hp_r_channel_h(a1),d1
  1224.              move.w   d0,(AU_VOL,a0,d1.w)      ; Volume -> 0
  1225.              btst.b   #AUFB_16BITS,hp_flags(a1)
  1226.              beq.s    ASM_audio_stop2    ; 8 bits
  1227.              move.w   hp_l_channel_l(a1),d1
  1228.              move.w   d0,(AU_VOL,a0,d1.w)      ; Volume -> 0
  1229.              move.w   hp_r_channel_l(a1),d1
  1230.              move.w   d0,(AU_VOL,a0,d1.w)      ; Volume -> 0
  1231. ASM_audio_stop2
  1232.              move.w   hp_audena(a1),$96(a0)    ; DMACON AUDxEN -> 0
  1233.              move.w   hp_adkcon(a1),$9E(a0)    ; ADKCON clr all audio bits
  1234.              move.w   hp_intdis(a1),$9C(a0)    ; Clr audio x interrupts
  1235.              move.w   hp_intdis(a1),$9A(a0)    ; INTENA audio 0 -> 0
  1236.              rts
  1237.  
  1238. ;             Audio set filter
  1239. ;
  1240. ;             a1 = struct hard_port *hport
  1241. ;
  1242. @ASM_audio_filter
  1243.              lea      $BFE001,a0
  1244.              btst.b   #AUFB_FILTER,hp_flags(a1)
  1245.              bne.s    ASM_audio_filter5
  1246.              bset     #1,(a0)
  1247.              bra.s    ASM_audio_filter9
  1248. ASM_audio_filter5    bclr     #1,(a0)
  1249. ASM_audio_filter9    rts
  1250.  
  1251.  
  1252. ;             Audio set volume
  1253. ;
  1254. ;             a1 = struct hard_port *hport
  1255. ;
  1256. @ASM_audio_vol
  1257.              lea      _custom,a0
  1258.              move.w   hp_l_channel_h(a1),d0
  1259.              move.w   hp_r_channel_h(a1),d1
  1260.              btst.b   #AUFB_16BITS,hp_flags(a1)
  1261.              bne.w    ASM_audio_vol5         ; 16 bits
  1262.              move.w   hp_l_vol(a1),(AU_VOL,a0,d0.w)
  1263.              move.w   hp_r_vol(a1),(AU_VOL,a0,d1.w)
  1264. ASM_audio_vol5         rts
  1265.  
  1266. ;             Audio set period
  1267. ;
  1268. ;             a1 = struct hard_port *hport
  1269. ;             d0.l = period
  1270. ;
  1271. @ASM_audio_per
  1272.              movem.l  d2-d7,-(sp)
  1273.              lea      _custom,a0
  1274. ;              move.l   hp_active_wave(a1),d1
  1275. ;              bchg     #0,d1
  1276. ;              move.l   (hp_current_period,a1,d1.w*4),d0
  1277.              move.w   hp_l_channel_h(a1),d4
  1278.              move.w   hp_r_channel_h(a1),d5
  1279.              CALLEXEC Disable
  1280.              btst.b   #AUFB_16BITS,hp_flags(a1)
  1281.              bne.w    ASM_audio_per5        ; 16 bits
  1282.              move.w   d0,(AU_PER,a0,d4.w)
  1283.              move.w   d0,(AU_PER,a0,d5.w)
  1284.              bra.s    ASM_audio_per9
  1285. ASM_audio_per5
  1286.              move.w   hp_l_channel_l(a1),d6
  1287.              move.w   hp_r_channel_l(a1),d7
  1288.              move.w   d0,(AU_PER,a0,d4.w)
  1289.              move.w   d0,(AU_PER,a0,d6.w)
  1290.              move.w   d0,(AU_PER,a0,d5.w)
  1291.              move.w   d0,(AU_PER,a0,d7.w)
  1292. ASM_audio_per9
  1293.              CALLEXEC Enable
  1294.              movem.l  (sp)+,d2-d7
  1295.              rts
  1296.  
  1297. ;             Audio write wave
  1298. ;
  1299. ;             a1 = struct hard_port *hport
  1300. ;
  1301. @ASM_audio_write
  1302.              movem.l  d2-d7,-(sp)
  1303.              lea      _custom,a0
  1304.              move.l   hp_active_wave(a1),d1
  1305.              asl.l    #2,d1              ; d1*4
  1306.              move.l   hp_wave_period(a1,d1.l),d0
  1307.              move.l   d0,hp_next_period(a1)
  1308.              move.w   hp_l_channel_h(a1),d4
  1309.              move.w   hp_r_channel_h(a1),d5
  1310.              CALLEXEC Disable
  1311.              btst.b   #AUFB_16BITS,hp_flags(a1)
  1312.              bne.w    ASM_audio_wr5          ; 16 bits
  1313.              tst.b    hp_playing(a1)          ;#5
  1314.              bne      ASM_audio_wr0
  1315.              move.w   d0,(AU_PER,a0,d4.w)
  1316.              move.w   d0,(AU_PER,a0,d5.w)
  1317. ASM_audio_wr0
  1318.              move.w   hp_l_vol(a1),(AU_VOL,a0,d4.w)
  1319.              move.w   hp_r_vol(a1),(AU_VOL,a0,d5.w)
  1320.              move.l   hp_l_wave_h(a1,d1.l),d0
  1321.              move.l   d0,(AU_PTR,a0,d4.w)
  1322.              btst     #AUFB_STEREO,hp_flags(a1)
  1323.              beq.s    ASM_audio_wr1         ; Mono output
  1324.              move.l   hp_r_wave_h(a1,d1.l),d0
  1325. ASM_audio_wr1         move.l   d0,(AU_PTR,a0,d5.w)
  1326.  
  1327.              clr.b    hp_end_of_play(a1)         ; Not end of play ?
  1328.              move.l   hp_wave_length(a1,d1.l),d0
  1329.              asr.l    #1,d0             ; Count in word
  1330.              move.w   d0,(AU_LEN,a0,d4.w)
  1331.              move.w   d0,(AU_LEN,a0,d5.w)
  1332.  
  1333.              bne.w    ASM_audio_wr7          ; Ok wave_length > 0 -> play audio
  1334.              st.b     hp_end_of_play(a1)      ; wave_length = 0 -> end of play
  1335.              bra.w    ASM_audio_wr7
  1336.  
  1337. ASM_audio_wr5
  1338.              move.w   hp_l_channel_l(a1),d6
  1339.              move.w   hp_r_channel_l(a1),d7
  1340.              tst.b    hp_playing(a1)          ;#5
  1341.              bne      ASM_audio_wr50
  1342.              move.w   d0,(AU_PER,a0,d4.w)
  1343.              move.w   d0,(AU_PER,a0,d6.w)
  1344.              move.w   d0,(AU_PER,a0,d5.w)
  1345.              move.w   d0,(AU_PER,a0,d7.w)
  1346. ASM_audio_wr50
  1347.              moveq.w  #$40,d0
  1348.              move.w   d0,(AU_VOL,a0,d4.w)
  1349.              move.w   d0,(AU_VOL,a0,d5.w)
  1350.              moveq.w  #$01,d0
  1351.              move.w   d0,(AU_VOL,a0,d6.w)
  1352.              move.w   d0,(AU_VOL,a0,d7.w)
  1353.              move.l   hp_l_wave_h(a1,d1.l),d0
  1354.              move.l   hp_l_wave_l(a1,d1.l),d2
  1355.              move.l   d0,(AU_PTR,a0,d4.w)
  1356.              move.l   d2,(AU_PTR,a0,d6.w)
  1357.              btst     #AUFB_STEREO,hp_flags(a1)
  1358.              beq.s    ASM_audio_wr6         ; Mono output
  1359.              move.l   hp_r_wave_h(a1,d1.l),d0
  1360.              move.l   hp_r_wave_l(a1,d1.l),d2
  1361. ASM_audio_wr6         move.l   d0,(AU_PTR,a0,d5.w)
  1362.              move.l   d2,(AU_PTR,a0,d7.w)
  1363.  
  1364.              clr.b    hp_end_of_play(a1)         ; Not end of play ?
  1365.              move.l   hp_wave_length(a1,d1.l),d0
  1366.              asr.l    #1,d0             ; Count in word
  1367.              move.w   d0,(AU_LEN,a0,d4.w)
  1368.              move.w   d0,(AU_LEN,a0,d5.w)
  1369.              move.w   d0,(AU_LEN,a0,d6.w)
  1370.              move.w   d0,(AU_LEN,a0,d7.w)
  1371.  
  1372.              bne.s    ASM_audio_wr7          ; Ok wave_length > 0 -> play audio
  1373.              st.b     hp_end_of_play(a1)      ; wave_length = 0 -> end of play
  1374. ASM_audio_wr7
  1375.              tst.b    hp_playing(a1)
  1376.              bne.s    ASM_audio_wr9          ; Always playing (started)
  1377.              st.b     hp_playing(a1)          ; Started
  1378.              move.w   hp_audena(a1),d0
  1379.              bset     #15,d0
  1380.              move.w   d0,$96(a0)              ; DMACON AUDxEN -> 1
  1381.              move.w   hp_adkcon(a1),$9E(a0)   ; ADKCON clr all audio bits
  1382.              move.w   hp_intdis(a1),$9C(a0)   ; Clr audio x interrupts
  1383.              move.w   hp_intena(a1),$9A(a0)   ; INTENA audio 0 -> 1
  1384. ASM_audio_wr9
  1385.              st.b     hp_dma_loaded(a1)       ; Dma is loaded
  1386.              CALLEXEC Enable
  1387.              movem.l  (sp)+,d2-d7
  1388.              rts
  1389.  
  1390. ;             Audio interrupt handler
  1391. ;
  1392. ;             a1 = DATA = struct hard_port *hport
  1393. ;
  1394. @ASM_audio_handler
  1395.              lea      _custom,a0
  1396.              move.w   hp_intdis(a1),$9C(a0)   ; Clr audio x interrupts
  1397.              move.l   hp_next_period(a1),d0
  1398.              bsr      @ASM_audio_per          ; #5
  1399.              tst.b    hp_dma_loaded(a1)
  1400.              bne.s    ASM_audio_handler1      ; Ok DMA was loaded -> signal
  1401.              bsr      @ASM_audio_stop          ; DMA is empty !!! -> stop audio, no signal
  1402.              bra.s    ASM_audio_handler9
  1403. ASM_audio_handler1
  1404.              clr.b    hp_dma_loaded(a1)       ; DMA become free
  1405.              tst.b    hp_end_of_play(a1)      ; end of play ?
  1406.              beq.s    ASM_audio_handler2
  1407.              bsr      @ASM_audio_stop
  1408. ASM_audio_handler2
  1409.              move.l   hp_signal(a1),d1
  1410.              clr.l    d0
  1411.              bset     d1,d0
  1412.              move.l   hp_task(a1),a1
  1413.              CALLEXEC Signal
  1414. ASM_audio_handler9
  1415.              clr.l    d0
  1416.              rts
  1417.  
  1418.